package main

//reference
//理解 Hystrix-go 中的 RollingCount 实现 https://pandaychen.github.io/2020/04/01/A-BUCKET-OF-HYSTRIX-ANALYSIS/
// thoughtworks microservices https://insights.thoughtworks.cn/tag/microservices/
// 软件大师 https://martinfowler.com/



import (
"fmt"
"github.com/pkg/errors"
"time"
)

//v1 版本
//缺点: 参数不可配置(functional options) ; 代码不优雅

func V2main(){
	//创建一个 circuit
	c := NewCircuitV2(circuit{})
	fmt.Println(c)
	//调用 10 次成功
	for i := 0; i < 11; i++ {
		c.IncrementSuccessV2()
		//fmt.Println(res, err)
	}
	fmt.Println(c)
	//调用 10 次失败,触发熔断开关
	for i := 0; i < 11; i++ {
		c.IncrementFailedV2()
		//fmt.Println(res, err)
	}
	fmt.Println(c)
	//重置开关,不会成功
	c = c.ResetV2()
	fmt.Println(c)

	time.Sleep(time.Second * 60)
	//会成功
	c = c.ResetV2()
	fmt.Println(c)
}

type circuitV2 struct {
	Success int
	Failed int
	status bool //暂时不存在half-open
	sleepTime int64
	statusTime time.Time
}

func NewCircuitV2(c circuit) *circuit{
	c.Success = 0
	c.Failed = 0
	c.status = false
	c.statusTime = time.Now()
	c.sleepTime = 60
	return &c
}
func (c *circuit) IncrementSuccessV2() (bool, error){
	if c.GetStatus() == false {
		c.Success++
		return true, errors.New("IncrementSuccess success")
	}
	return false, errors.New("IncrementSuccess failed")
}
func (c *circuit) IncrementFailedV2() (bool, error){
	//熔断器关闭状态
	if c.GetStatus() == false {
		c.Failed++
		//失败 10 次
		if c.Failed > 10 {
			//打开熔断器
			c.Open()
			return false, errors.New("IncrementFailed failed")
		} else {
			return true, errors.New("IncrementFailed success")
		}
	} else {
		return false, errors.New("IncrementFailed status is OPENED")
	}
}


type brokerV2 interface {
	GetStatusV2() bool
	OpenV2()
	CloseV2()
	ResetV2()
}

func (c *circuit) ResetV2() *circuit{
	//如果在时间窗口,不重置状态
	if c.statusTime.Unix() + c.sleepTime > time.Now().Unix(){
		return c
	}
	//超出时间窗口,重置状态
	return NewCircuit(circuit{})
}
func (c *circuit) GetStatusV2() bool{
	return c.status
}
func (c *circuit) OpenV2(){
	c.status = true
}
func (c *circuit) CloseV2(){
	c.status = false
}
